<script setup lang="ts">
import { computed, onMounted, reactive, ref, watch, h } from 'vue'
import Request from '@/api/axios'
import { EditorStore } from '@/stores/editor'
import { PlusOutlined, FolderOpenOutlined } from '@ant-design/icons-vue'
import { nextTick } from 'vue'
import { options } from '@/components/MonacoEditor/monaco.config'
import { defineAsyncComponent } from 'vue'
import { message } from 'ant-design-vue'
import { useLocalStorage } from '@/utils/useLocalStorage'
const theme = useLocalStorage('editor_theme', 'vs-dark')
// @ts-ignore
import { readFileSystem } from '@/utils/fileSystem'
import { cloneDeep } from 'lodash'
import hljs from '@/assets/highlight/highlight.min.js'
import { HttpStatusCode } from 'axios'
import Select from '@/components/Select.vue'
import TestCase from './components/TestCase.vue'

const editorStore = EditorStore()
const { addCodeStore, removeCodeStore, getCodeStore } = editorStore
const visible = computed(() => {
    return editableTabs.value.length > 0
})
const editableTabs = ref<any[]>([])
const currentData = reactive({
    language: 'cpp',
    code: '',
    cases: [
        {
            input: '',
            output: ''
        }
    ]
})
const initData = {
    code: '',
    cases: [
        {
            input: '',
            output: ''
        }
    ],
    language: 'cpp'
}
const activeKey = ref(0)

onMounted(() => {
    let Store = getCodeStore()
    if (Store.length == 0) {
        editableTabs.value.push(cloneDeep(initData))
    } else editableTabs.value = Store
    activeKey.value = 0
    watch(
        [activeKey],
        () => {
            let currentTab = editableTabs.value[activeKey.value]
            currentData.code = currentTab.code
            currentData.cases = currentTab.cases
            currentData.language = currentTab.language
        },
        { immediate: true }
    )
})

watch(
    currentData,
    () => {
        editableTabs.value[activeKey.value].code = currentData.code
        editableTabs.value[activeKey.value].language = currentData.language
        editableTabs.value[activeKey.value].cases = currentData.cases
        addCodeStore(editableTabs.value)
    },
    { deep: true }
)

const handleEditorChange = (newValue: any) => {
    currentData.code = newValue
    currentData.language =
        hljs.highlightAuto(newValue, ['c', 'cpp', 'python', 'javascript', 'rust', 'go']).language ??
        'text'
}

const SubmitCode = async () => {
    loading.value = true
    for (const item of currentData.cases) item.output = ''

    await Request.post({
        url: `/ide/submit`,
        data: {
            submission_id: 12432345,
            code: currentData.code,
            language: currentData.language,
            test_cases: currentData.cases.map((i, index) => ({
                case_id: index + 1,
                stdin: i.input,
                expected: ""
            })),
            message: "",
            seccomp_profile: "",
            resources_limits: {
                cpu_time: 100000,
                memory_bytes: 67108864,
                stack_bytes: 10485760,
                output_bytes: 10485760,
            }
        },
        timeout: 10 * 1000 // 60 sec
    })
        .then((res: any) => {
            if(res.info.verdict == "CompilationError") {
                currentData.cases[0].output = res.info.result[0].stderr ?? ''
            }
            if (res.info.verdict == "WrongAnswer"){
                res.info.result.forEach((item, index) => {
                    currentData.cases[index].output = item.stdout ?? item.stderr ?? ''
                })
            }
        })
        .catch((err: any) => {
            console.log(err)

        })
        .finally(() => (loading.value = false))
}

const languageOptions = ['cpp', 'c', 'python', 'javascript', 'rust', 'go'].map((i) => {
    return { value: i, label: i }
})

const getTitle = (index: number) => {
    return '文件' + (index + 1)
}

const add = () => {
    editableTabs.value.push({
        theme: 'vs-dark',
        code: '',
        cases: [{ input: '', output: '' }],
        language: 'cpp'
    })
    activeKey.value = editableTabs.value.length - 1
}
const remove = (targetKey: string) => {
    editableTabs.value = editableTabs.value.filter((tab, index) => {
        return index.toString() != targetKey
    })
    activeKey.value = editableTabs.value.length - 1
}
const onEdit = (targetKey: string | MouseEvent, action: string) => {
    if (action === 'add') add()
    else remove(targetKey as string)
}
const loading = ref(false)

const Monaco = defineAsyncComponent(() => import('@/components/MonacoEditor/Monaco.vue'))
</script>

<template>
    <a-tabs type="editable-card" :activeKey="activeKey" :closable="true" @edit="onEdit"
        @change="(_Key) => (activeKey = _Key)">
        <a-tab-pane v-for="(item, index) in editableTabs" :key="index" :tab="getTitle(index)" :closable="true"
            :disabled="loading">
        </a-tab-pane>
    </a-tabs>
    <div style="height: 80vh" v-show="visible">
        <el-splitter>
            <el-splitter-panel size="50%" :min="200">
                <div class="justify-center items-center my-0 mx-auto">
                    <a-row :gutter="20" class="editor-toolbar">
                        <a-col :span="6">
                            <Select class="w-11/12" @update:value="($event) => (currentData.language = $event)"
                                :options="languageOptions" :value="currentData.language" />
                        </a-col>
                        <a-col :span="6">
                            <a-button type="dashed" class="file-button" @click="
                                () => {
                                    readFileSystem()
                                        .then((content) => handleEditorChange(content))
                                        .catch((error) => {
                                            ; (message.error('出错啦'), console.log(error))
                                        })
                                }
                            ">
                                <template #icon>
                                    <FolderOpenOutlined />
                                </template>
                                从文件读取
                            </a-button>
                        </a-col>
                        <a-col :span="6">
                            <a-popover placement="bottom" trigger="hover" overlayClassName="env-popover">
                                <template #content>
                                    <div class="env-table">
                                        <div class="env-row" v-for="(libs, lang) in {
                                            'C++': 'folly, fmt, boost, pthread, double-conversion, fast_float',
                                            'Python': 'numpy, pandas, scipy',
                                            'Rust': 'tokio, hyper',
                                            'JavaScript': 'node.js',
                                            'Go': '无',
                                            'C': 'pthread'
                                        }" :key="lang">
                                            <span class="env-lang">{{ lang }}</span>
                                            <span class="env-libs">{{ libs }}</span>
                                        </div>
                                    </div>
                                </template>
                                <a-button type="link" class="env-button">
                                    <template #icon>
                                        <component :is="h('span', { class: 'env-icon' }, '🔧')" />
                                    </template>
                                    运行环境
                                </a-button>
                            </a-popover>
                        </a-col>
                        <a-col :span="6">
                            <a-button :loading="loading" type="primary" class="submit-button" @click="SubmitCode">
                                提交
                            </a-button>
                        </a-col>
                    </a-row>
                    <keep-alive>
                        <Monaco @change="handleEditorChange" v-model:value="currentData.code" :theme="theme"
                            :language="currentData.language" :options="options" />
                    </keep-alive>
                </div>
            </el-splitter-panel>
            <el-splitter-panel size="50%">
                <TestCase v-model:test_cases="currentData.cases" />
            </el-splitter-panel>
        </el-splitter>
    </div>
</template>

<style scoped>
.editor-toolbar {
    padding: 16px;
    background: var(--bg-secondary);
    border-radius: 8px;
    margin-bottom: 16px;
}

.file-button {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
}

.env-button {
    display: flex;
    align-items: center;
    gap: 4px;
    font-size: 14px;
}

.env-icon {
    font-size: 16px;
}

.submit-button {
    width: 100%;
}

.env-table {
    min-width: 300px;
    padding: 8px;
}

.env-row {
    display: flex;
    padding: 8px 0;
    border-bottom: 1px solid var(--border-color);
}

.env-row:last-child {
    border-bottom: none;
}

.env-lang {
    width: 100px;
    font-weight: 500;
    color: var(--primary-color);
}

.env-libs {
    flex: 1;
    color: var(--text-secondary);
}

:deep(.env-popover) {
    .ant-popover-inner {
        background: var(--bg-secondary);
        border: 1px solid var(--border-color);
        border-radius: 8px;
    }

    .ant-popover-arrow-content {
        background: var(--bg-secondary);
    }
}
</style>
